﻿using System;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using VSeWSS;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.Utilities;
using System.Collections.Generic;
using de.rwth.rz.campus.sputils.ItemEventReceiverHelper;
using de.rwth.rz.campus.sharepointutils.EMail;
using de.rwth.rz.campus.sharepointutils.UsersAndGroups;
using Microsoft.SharePoint.Administration;
using System.Text;
using System.Resources;
using System.Reflection;
using System.Globalization;

namespace de.rwth.rz.campus.sharepointutils.GMEventRecevier
{
    /// <remarks>
    /// 
    /// Copyright 2010 RWTH Aachen, CAMPUS Labs
    /// 
    /// Licensed under the Apache License, Version 2.0 (the "License");
    /// you may not use this file except in compliance with the License.
    /// You may obtain a copy of the License at
    ///
    /// http://www.apache.org/licenses/LICENSE-2.0
    ///
    /// Unless required by applicable law or agreed to in writing, software
    /// distributed under the License is distributed on an "AS IS" BASIS,
    /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    /// See the License for the specific language governing permissions and
    /// limitations under the License.
    /// 
    /// </remarks>
    [CLSCompliant(false)]
    [Guid("49222163-6d38-4230-8e03-7ace34910563")]
    public class GMEventReceiverItemEventReceiver : SPItemEventReceiver
    {
        //Field Information:
        //ID="{1666D8EA-D8B8-4db9-A32F-8F72B6EBF58B}" Name="GroupField"  (Gruppen)
        //ID="{15F259A2-3EE8-439f-8BEE-F4280B5B2EE7}" Name="CarbonCopyField"  (Cc)
        //ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title"  (Betreff)
        //ID="{7662cd2c-f069-4dba-9e35-082cf976e170}" Name="Body"   (Body HTML)
        //ID="{A33B83F4-E29B-4b15-9253-111266B7745B}" Name="PriorityField"  (Prio)
        //ID="{9da97a8a-1da5-4a77-98d3-4bc10456e700}" Name="Comments"   (Log)
        //ID="{fc2e188e-ba91-48c9-9dd3-16431afddd50}" Name="WorkAddress"  (Body Text)
        //ID="{c4e0f350-52cc-4ede-904c-dd71a3d11f7d}" Name="WorkCity" (Error)
        //ID="{6ca7bd7f-b490-402e-af1b-2813cf087b1e}" Name="JobTitle" (Sent)

        private static Guid logField = new Guid("{9da97a8a-1da5-4a77-98d3-4bc10456e700}");
        private static Guid toField = new Guid("{1666D8EA-D8B8-4db9-A32F-8F72B6EBF58B}");
        private static Guid othersField = new Guid("{15F259A2-3EE8-439f-8BEE-F4280B5B2EE7}");
        private static Guid subjectField = new Guid("{fa564e0f-0c70-4ab9-b863-0177e6ddd247}");
        private static Guid messageHTMLField = new Guid("{7662cd2c-f069-4dba-9e35-082cf976e170}");
        private static Guid messageTextField = new Guid("{fc2e188e-ba91-48c9-9dd3-16431afddd50}");
        private static Guid priorityField = new Guid("{A33B83F4-E29B-4b15-9253-111266B7745B}");
        private static SPContentTypeId htmlContentType = new SPContentTypeId("0x01009AD118F216DE41D181E0A33C501B59AF");
        private static Guid sentField = new Guid("{6ca7bd7f-b490-402e-af1b-2813cf087b1e}");
        private static Guid errorField = new Guid("{c4e0f350-52cc-4ede-904c-dd71a3d11f7d}");

        /// <summary>
        /// Initializes a new instance of the Microsoft.SharePoint.SPItemEventReceiver class.
        /// </summary>
        public GMEventReceiverItemEventReceiver()
        {
        }

        /// <summary>
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ContextEvent(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Asynchronous after event that occurs after a new elevateditem has been added to its containing object.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            SPListItem spliGroupMail = properties.ListItem;
            if (spliGroupMail != null)
            {
                List<SPGroup> spGroups = new List<SPGroup>();
                foreach (String group in ItemEventReceiverHelper.GetValues(spliGroupMail[toField]))
                {
                    SPGroup groupname = Groups.FindGroup(properties.OpenWeb(), group);
                    spGroups.Add(groupname);
                }

                ItemEventReceiverHelper.SetListItemPermissions(spliGroupMail, spGroups, properties.OpenWeb().CurrentUser);
                DisableEventFiring();
                spliGroupMail.Update();
                EnableEventFiring();
            }

        }

        /// <summary>
        /// Synchronous before event that occurs when a new elevateditem is added to its containing object.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        public override void ItemAdding(SPItemEventProperties properties)
        {
            String toKey = String.Empty;
            String othersKey = String.Empty;
            String subjectKey = String.Empty;
            String htmlContentTypeString = String.Empty;
            String messageHTMLKey = String.Empty;
            String messageTextKey = String.Empty;
            String priorityKey = String.Empty;
            String logKey = String.Empty;
            String sentKey = String.Empty;
            String errorKey = String.Empty;
            SPContentType uniqueContentType = null;
            uint lang;
            String webname = String.Empty;
            String weburl = String.Empty;
            using (SPWeb web = properties.OpenWeb())
            {
                lang = web.Language;
                webname = web.Title;
                weburl = web.Url;
                //Get keys
                toKey = web.Lists[properties.ListId].Fields[toField].InternalName;
                othersKey = web.Lists[properties.ListId].Fields[othersField].InternalName;
                subjectKey = web.Lists[properties.ListId].Fields[subjectField].InternalName;
                foreach (SPContentType ct in web.Lists[properties.ListId].ContentTypes)
                {
                    if (ct.Id.IsChildOf(htmlContentType))
                    {
                        uniqueContentType = ct;
                    }
                }
                messageHTMLKey = web.Lists[properties.ListId].Fields[messageHTMLField].InternalName;
                messageTextKey = web.Lists[properties.ListId].Fields[messageTextField].InternalName;
                priorityKey = web.Lists[properties.ListId].Fields[priorityField].InternalName;
                logKey = web.Lists[properties.ListId].Fields[logField].InternalName;
                sentKey = web.Lists[properties.ListId].Fields[sentField].InternalName;
                errorKey = web.Lists[properties.ListId].Fields[errorField].InternalName;
            }
            //Use current user
            GroupMail gm = new GroupMail(properties.OpenWeb().CurrentUser);
            //Try to generate and send the mails
            try
            {
                //Use SP SMTP Server
                gm.SetSPSMTPServer(SPWebService.ContentService.WebApplications);
                //To
                foreach (String group in ItemEventReceiverHelper.GetValues(properties.AfterProperties[toKey]))
                {
                    SPGroup groupname = Groups.FindGroup(properties.OpenWeb(), group);
                    if (groupname != null)
                    {
                        gm.AddGroup(groupname);
                    }
                }
                //CC
                foreach (String cc in ItemEventReceiverHelper.GetOthers(properties.AfterProperties[othersKey]))
                {
                    gm.AddOther(cc);
                }
                //Subject
                gm.Subject = properties.AfterProperties[subjectKey].ToString();
                //Format
                if (((String)properties.AfterProperties["ContentType"]) == uniqueContentType.Name)
                {
                    gm.IsHTML = true;
                    //Message
                    if (properties.AfterProperties[messageHTMLKey] != null)
                    {
                        gm.Message = properties.AfterProperties[messageHTMLKey].ToString();
                    }
                }
                else
                {
                    gm.IsHTML = false;
                    //Message
                    if (properties.AfterProperties[messageTextKey] != null)
                    {
                        gm.Message = properties.AfterProperties[messageTextKey].ToString();
                    }
                }
                //Footer
                GenerateFooter(gm, lang, webname, weburl);

                //Priority
                String low = SPUtility.GetLocalizedString("$Resources:Mailer,MailPriority_Low", "Mailer", lang);
                String high = SPUtility.GetLocalizedString("$Resources:Mailer,MailPriority_High", "Mailer", lang);
                if (properties.AfterProperties[priorityKey] != null)
                {
                    gm.Priority = System.Net.Mail.MailPriority.Normal;
                    if (properties.AfterProperties[priorityKey].ToString() == low)
                    {
                        gm.Priority = System.Net.Mail.MailPriority.Low;
                    }
                    else if (properties.AfterProperties[priorityKey].ToString() == high)
                    {
                        gm.Priority = System.Net.Mail.MailPriority.High;
                    }
                }
                //ItemEventReceiverHelper.SetListItemPermissions(spliGroupMail, gm.GetAddedGroups(), properties.OpenWeb().CurrentUser);
                properties.AfterProperties[logKey] = gm.SendGroupMail(properties.OpenWeb());
            }
            catch (Exception e)
            {
                StringBuilder eMessage = new StringBuilder(e.Message);
                foreach (String s in gm.LogMessages)
                {
                    eMessage.AppendLine(s);
                }
                properties.AfterProperties[logKey] = eMessage.ToString();
            }
            finally
            {
                properties.AfterProperties[sentKey] = gm.MailsSent.ToString();
                properties.AfterProperties[errorKey] = gm.MailsWithError.ToString();
            }
        }

        //http://tools.ietf.org/html/rfc1855
        private static void GenerateFooter(GroupMail gm, uint lang, String webname, String weburl)
        {
            StringBuilder footer = new StringBuilder(String.Empty);
            if (gm.IsHTML)
            {
                footer.AppendLine();
                footer.AppendLine("<p style=\"font-size:0.7em;\">");
                footer.AppendLine("-- ");
                footer.AppendLine("<br />");
                footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part1", "Mailer", lang));
                footer.Append(" ");
                footer.Append("<a href=\"" + weburl + "\">" + webname + "</a>");
                footer.Append(" ");
                footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part2", "Mailer", lang));
                footer.Append(" ");
                if (gm.GetAddedGroups().Count == 1)
                {
                    footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part3", "Mailer", lang));
                }
                else
                {
                    footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part4", "Mailer", lang));
                }
                footer.Append(" ");
                foreach (SPGroup group in gm.GetAddedGroups())
                {
                    footer.Append("\"");
                    footer.Append(group.Name);
                    footer.Append("\"");
                    footer.Append(", ");
                }
                footer.Remove(footer.Length - 2, 1);
                // Uncomment, if you want to see the others stuff in every email.
                //if (gm.GetOthers().Count > 0)
                //{
                //    footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part5", "Mailer", lang));
                //    footer.Append(" ");
                //    foreach (String otherEmail in gm.GetOthers())
                //    {
                //        footer.Append(otherEmail);
                //        footer.Append(", ");
                //    }
                //    footer.Remove(footer.Length - 2, 1);
                //}
                footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part6", "Mailer", lang));
                footer.AppendLine(".");
                footer.AppendLine("</p>");
            }
            else
            {
                footer.AppendLine();
                footer.AppendLine();
                footer.AppendLine("-- ");
                footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part1", "Mailer", lang));
                footer.Append(" ");
                footer.Append(webname + " <" + weburl + ">");
                footer.Append(" ");
                footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part2", "Mailer", lang));
                footer.Append(" ");
                if (gm.GetAddedGroups().Count == 1)
                {
                    footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part3", "Mailer", lang));
                }
                else
                {
                    footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part4", "Mailer", lang));
                }
                footer.Append(" ");
                foreach (SPGroup group in gm.GetAddedGroups())
                {
                    footer.Append("\"");
                    footer.Append(group.Name);
                    footer.Append("\"");
                    footer.Append(", ");
                }
                footer.Remove(footer.Length - 2, 1);
                // Uncomment, if you want to see the others stuff in every email.
                //if (gm.GetOthers().Count > 0)
                //{
                //    footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part5", "Mailer", lang));
                //    footer.Append(" ");
                //    foreach (String otherEmail in gm.GetOthers())
                //    {
                //        footer.Append(otherEmail);
                //        footer.Append(", ");
                //    }
                //    footer.Remove(footer.Length - 2, 1);
                //}
                footer.Append(SPUtility.GetLocalizedString("$Resources:Mailer,Footer_Part6", "Mailer", lang));
                footer.AppendLine(".");
            }
            gm.Message += footer.ToString();
        }

        /// <summary>
        /// Asynchronous after event that occurs after a user adds an attachment to an elevateditem.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemAttachmentAdded(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Synchronous before event that occurs when a user adds an attachment to an elevateditem.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemAttachmentAdding(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Asynchronous after event that occurs when after a user removes an attachment from an elevateditem.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemAttachmentDeleted(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Synchronous before event that occurs when a user removes an attachment from an elevateditem.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemAttachmentDeleting(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Asynchronous after event that occurs after an elevateditem is checked in.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemCheckedIn(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Asynchronous after event that occurs after an elevateditem is checked out.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemCheckedOut(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Synchronous before event that occurs as a file is being checked in.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemCheckingIn(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Synchronous before event that occurs after an elevateditem is checked out.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemCheckingOut(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Asynchronous after event that occurs after an existing elevateditem is completely deleted.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemDeleted(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Synchronous before event that occurs before an existing elevateditem is completely deleted.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemDeleting(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// </summary>
        /// <param name="properties">
        /// </param>
        //public override void ItemFileConverted(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Occurs after a file is moved.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemFileMoved(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Occurs when a file is being moved.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemFileMoving(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Synchronous before event that occurs as an elevateditem is being unchecked out.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemUncheckedOut(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Synchronous before event that occurs as an elevateditem is being unchecked out.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemUncheckingOut(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Asynchronous after event that occurs after an existing elevateditem is changed, for example, when the user changes data in one or more fields.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        //public override void ItemUpdated(SPItemEventProperties properties)
        //{
        //}

        /// <summary>
        /// Synchronous before event that occurs when an existing elevateditem is changed, for example, when the user changes data in one or more fields.
        /// </summary>
        /// <param name="properties">
        /// A Microsoft.SharePoint.SPItemEventProperties object that represents properties of the event handler.
        /// </param>
        public override void ItemUpdating(SPItemEventProperties properties)
        {
            //Updating is NEVER allowed
            properties.Status = SPEventReceiverStatus.CancelWithError;
            using (SPWeb web = properties.OpenWeb())
            {
                uint lang = web.Language;
                properties.ErrorMessage = SPUtility.GetLocalizedString("$Resources:Mailer,ErrorMsg", "Mailer", lang);
            }
            properties.Cancel = true;
        }
    }
}

